              package com.java.diagnostics.visualizer.displayer.plot;
              
              import com.java.diagnostics.visualizer.coredisplayers.util.Messages;
              import com.java.diagnostics.visualizer.data.AggregateData;
              import com.java.diagnostics.visualizer.data.DataPoint;
              import com.java.diagnostics.visualizer.data.DataSet;
              import com.java.diagnostics.visualizer.data.TupleData;
              import com.java.diagnostics.visualizer.data.Variant;
              import com.java.diagnostics.visualizer.data.axes.Axis;
              import com.java.diagnostics.visualizer.data.axes.DataAxis;
              import com.java.diagnostics.visualizer.data.axes.UnitConverterDefinition;
              import com.java.diagnostics.visualizer.data.axes.YDataAxis;
              import com.java.diagnostics.visualizer.data.ids.ID;
              import com.java.diagnostics.visualizer.display.AxisSelection;
              import com.java.diagnostics.visualizer.display.DataPointSelection;
              import com.java.diagnostics.visualizer.display.HoverableDisplayer;
              import com.java.diagnostics.visualizer.display.SequenceIDAwareDisplayer;
              import com.java.diagnostics.visualizer.impl.colours.Colours;
              import com.java.diagnostics.visualizer.impl.display.DataDisplayerImpl;
              import com.java.diagnostics.visualizer.impl.factory.LogFactory;
              import com.java.diagnostics.visualizer.impl.selection.GCAndMemoryVisualizerSelectionProvider;
              import com.java.diagnostics.visualizer.parser.vgc.constants.VGCAxes;
              import com.java.diagnostics.visualizer.properties.IDsToDisplayProperties;
              import com.java.diagnostics.visualizer.properties.OutputProperties;

              import java.text.MessageFormat;
              import java.util.Collection;
              import java.util.HashMap;
              import java.util.Iterator;
              import java.util.LinkedList;
              import java.util.List;
              import java.util.Map;
              import java.util.Map.Entry;
              import java.util.PriorityQueue;
              import java.util.Set;
              import java.util.TreeMap;
              import java.util.TreeSet;
              import java.util.logging.Level;
              import java.util.logging.Logger;

              import org.eclipse.jface.viewers.ISelection;
              import org.eclipse.jface.viewers.ISelectionProvider;
              import org.eclipse.jface.viewers.StructuredSelection;
           import org.eclipse.swt.SWT;
              import org.eclipse.swt.accessibility.Accessible;
              import org.eclipse.swt.accessibility.AccessibleAdapter;
              import org.eclipse.swt.accessibility.AccessibleControlAdapter;
              import org.eclipse.swt.accessibility.AccessibleControlEvent;
              import org.eclipse.swt.accessibility.AccessibleEvent;
              import org.eclipse.swt.dnd.Clipboard;
              import org.eclipse.swt.dnd.ImageTransfer;
              import org.eclipse.swt.dnd.Transfer;
              import org.eclipse.swt.events.MouseEvent;
              import org.eclipse.swt.events.MouseMoveListener;
              import org.eclipse.swt.graphics.Color;
              import org.eclipse.swt.graphics.Device;
              import org.eclipse.swt.graphics.Font;
              import org.eclipse.swt.graphics.FontData;
              import org.eclipse.swt.graphics.GC;
              import org.eclipse.swt.graphics.Image;
              import org.eclipse.swt.graphics.ImageData;
              import org.eclipse.swt.graphics.ImageLoader;
              import org.eclipse.swt.graphics.Pattern;
              import org.eclipse.swt.graphics.Point;
              import org.eclipse.swt.graphics.Rectangle;
              import org.eclipse.swt.graphics.Transform;
              import org.eclipse.swt.printing.Printer;
              import org.eclipse.swt.widgets.Canvas;
              import org.eclipse.swt.widgets.Display;
              import org.eclipse.swt.widgets.Event;
              import org.eclipse.swt.widgets.Listener;
              import org.eclipse.swt.widgets.Shell;
              
              public class SWTPlotDataDisplayer extends DataDisplayerImpl
                implements Listener, SequenceIDAwareDisplayer, HoverableDisplayer, MouseMoveListener
              {
                private static final String UNIT_LABEL_FORMAT = "{0} ({1})";
                private static final String POINT_HOVERTEXT_FORMAT = Messages.getString("SWTPlotDataDisplayer.point.hover.text.format");
                private static final String SOMESTRING = "somestring";
                private static final int X_ENTENT_FOR_LABEL_SHRINKING = 60;
                private static final int LEGEND_LINE_LENGTH = 20;
                private static final int LEGEND_PADDING = 20;
                private static final int DEFAULT_HEIGHT = 500;
                private static final int DEFAULT_WIDTH = 700;
                private static final int OVAL_SIZE = 3;
                private static final String WILDCARD = "*";
                private static final Logger TRACE = LogFactory.getTrace(SWTPlotDataDisplayer.class);
              
                private Colours colours = null;
                private DataSet dataSet = null;
                protected OutputProperties outputProperties = null;
                private static final int border = 35;
                private int axisFontHeight = 8;
                private int infoHeight = this.axisFontHeight;
                private Map<DataAxis, String> biggestYNumberLabels;
                private static final int TICK_LENGTH = 10;
                private int width = 300;
                private int height = 300;
                protected int plotLeft;
                protected int plotRight;
                protected int plotTop;
                protected int plotBottom;
                private int plotHeight;
                private int plotWidth;
                private boolean padPlots;
                protected DataAxis xAxis;
                private int numFieldsToPlot = 0;
                private Canvas canvas;
                protected XPositionConverter xConverter;
                private static final int MIN_TICKS = 10;
                private int numTicks;
                private Map<Axis, Map<String, DataPoint>> pointRecord;
                protected LinePlotPreferenceHelper linePlotPreferencesHelper;
                private int position = 0;
                protected Map<YDataAxis, PointConverter> converters;
                private Font alternateLabelsFont;
                private Font smallLabelsFont;
                private Font smallAlternateLabelsFont;
                private int leftNumberLabelsWidth = 10;
                private int rightNumberLabelsWidth = 10;
                private static final int UNSET = -1;
                private ISelectionProvider selectionProvider;
                private DataAxis[] axes = new DataAxis[4];
                protected String accessibleMessage;
                private TreeSet<Integer> usedYTicksRight;
                private TreeSet<Integer> usedYTicksLeft;
              
                public SWTPlotDataDisplayer()
                {
                  this.linePlotPreferencesHelper = new LinePlotPreferenceHelper();
                  this.converters = new TreeMap();
                  this.biggestYNumberLabels = new TreeMap();
                  this.selectionProvider = new GCAndMemoryVisualizerSelectionProvider();
               
                }
              
                public Object display(DataSet dataSet, OutputProperties outputProperties) {
                  TRACE.entering(this.className, "display");
                  initialisePlot(dataSet, outputProperties);
                  TRACE.exiting(this.className, "display");
                  return this.canvas;
                }
              
                public void goToSequenceUID(int sequenceUID) {
                  if (TRACE.isLoggable(Level.FINE)) {
                    TRACE.fine("Trying to go to " + sequenceUID);
                  }
              
                  Iterator labels = this.outputProperties.getTupleFieldsToDisplay()
                    .getAllIDsToDisplay();
              
                  int labelIndex = -1;
                  Point position = null;
              
                  while ((labels.hasNext()) && (position == null)) {
                    labelIndex++;
                    ID id = (ID)labels.next();
              
                    if (this.dataSet != null)
                    {
                      Variant[] variants = this.dataSet.getVariants();
              
                      for (int m = 0; m < variants.length; m++) {
                        TupleData twoddata = variants[m].getTupleData(id);
                        if (twoddata != null) {
                          DataPoint point = twoddata.getDataPoint(sequenceUID);
                          if (point != null) {
                            PointConverter converter = getConverter(twoddata);
                            if (converter != null) {
                              position = converter.convertToPoint(point);
                            }
                          }
                        }
                      }
                    }
                  }
              
                  if (position != null)
                    Display.getCurrent().setCursorLocation(this.canvas.toDisplay(position));
                }
              
                private DataPoint getDataPoint(Point point)
                {
                  DataPoint dataPoint = null;
                  Iterator it = this.converters.values().iterator();
                  while ((dataPoint == null) && (it.hasNext())) {
                    dataPoint = ((PointConverter)it.next()).findDataPoint(point);
                  }
                  return dataPoint;
                }
              
                public int getSequenceUID(ISelection selection) {
                  int sequenceID = -1;
                  if ((selection instanceof DataPointSelection)) {
                    DataPointSelection pselection = (DataPointSelection)selection;
                    DataPoint dataPoint = pselection.getPoint();
                    if (dataPoint != null) {
                      sequenceID = dataPoint.getSequenceUID();
                    }
                  }
                  return sequenceID;
                }
              
                private void refreshCanvas(OutputProperties outputProperties)
                {
                  if ((this.canvas != null) && (!this.canvas.isDisposed())) {
                    this.canvas.removeListener(9, this);
                    this.canvas.removeMouseMoveListener(this);
                  }
                  this.canvas = 
                    ((Canvas)outputProperties
                    .getDisplayerProperties(getClass().getName()));
              
                  if ((this.canvas != null) && (!this.canvas.isDisposed())) {
                    this.canvas.addListener(9, this);
                 //added by wenguang.huang 
                 this.canvas.addListener(SWT.Paint, this);
                 this.canvas.addListener(SWT.SHEET, this);
				//added end by wenguang.huang 
                    this.canvas.addMouseMoveListener(this);
                    this.canvas.getAccessible().addAccessibleListener(
                      new AccessibleAdapter()
                    {
                      public void getName(AccessibleEvent e)
                      {
                        e.result = SWTPlotDataDisplayer.this.accessibleMessage;
                      }
                    });
                    AccessibleControlAdapter cAdaptor = new AccessibleControlAdapter()
                    {
                      public void getRole(AccessibleControlEvent e)
                      {
                        e.detail = 9;
                        super.getRole(e);
                      }
                    };
                    this.canvas.getAccessible().addAccessibleControlListener(cAdaptor);
                 
                  }
                }
              
                protected void initialisePlot(DataSet dataSet, OutputProperties outputProperties)
                {
                  this.pointRecord = new HashMap();
                  this.dataSet = dataSet;
                  this.outputProperties = outputProperties;
                
               //added by wenguang.huang 
               this.padPlots =true;
               this.position =5;
			   //added end by wenguang.huang 


               // deleted by wenguang.huang 
//          this.padPlots = this.linePlotPreferencesHelper.getPadPlots();
//          this.position = this.linePlotPreferencesHelper.getLegendPosition();
                  this.converters.clear();
              
                  refreshCanvas(outputProperties);
              
                  this.numFieldsToPlot = 0;
              
                  this.biggestYNumberLabels.clear();
              
                  this.xConverter = createXPositionConverter();
              
                  Iterator ids = outputProperties.getTupleFieldsToDisplay().getAllIDsToDisplay();
                    
// deleted by wenguang.huang 
//          int j;
//          int i;

//          for (i=0; ids.hasNext(); )
                   
//          {
//            ID id = (ID)ids.next();
//            Variant[] arrayOfVariant;
//            j = (arrayOfVariant = dataSet.getVariants()).length; 
                 //i = 0; 
                 //continue;
               //   Variant variant = arrayOfVariant[i];
                  //variant.get
//            TupleData data = variant.getTupleData(id);
                 //   if (data != null)
//            {
//              updateLabelsAndAxes(outputProperties, data);
//              this.numFieldsToPlot += 1;
                 //   }
//            i++;
                 // }
// deleted by wenguang.huang 
//added by wenguang.huang 
while (ids.hasNext()) {
    final ID id = (ID) ids.next();
    Variant[] variants;
    for (int length = (variants = dataSet.getVariants()).length, i = 0; i < length; ++i) {
        final Variant variant = variants[i];
        final TupleData data = variant.getTupleData(id);
        if (data != null) {
            this.updateLabelsAndAxes(outputProperties, data);
            ++this.numFieldsToPlot;
        }
    }
}

//added end by wenguang.huang 
              
                  Iterator it = this.converters.keySet().iterator();
              
                  while (it.hasNext()) {
                    DataAxis yAxis = (DataAxis)it.next();
              
                    PointConverter converter = (PointConverter)this.converters.get(yAxis);
              
                    converter.setCalculateLegendPosition(this.position == 0);
              
                    converter.getYConverter().updateLimits(500, 0);
                    double minYValue = converter.getYConverter().convertToValue(
                      500);
                    double maxYValue = converter.getYConverter()
                      .convertToValue(0);
              
                    double tickWidth = calculateTickWidthValue(maxYValue - minYValue);
                    int digits = (int)getFractionDigits(tickWidth);
                    String yUnits = outputProperties.getUnits(yAxis.getAxis());
              
                    String maxYLabel = yAxis.formatUnconverted(maxYValue, digits,yUnits);
                      
                    String minYLabel = yAxis.formatUnconverted(minYValue, digits,yUnits);
                      
                    String medYLabel = yAxis.formatUnconverted((minYValue + maxYValue) / 2.0D, digits, yUnits);
                      
              
                    if ((maxYLabel.length() > minYLabel.length()) && 
                      (maxYLabel.length() > medYLabel.length()))
                      this.biggestYNumberLabels.put(yAxis, maxYLabel);
                    else if (medYLabel.length() > minYLabel.length())
                      this.biggestYNumberLabels.put(yAxis, medYLabel);
                    else {
                      this.biggestYNumberLabels.put(yAxis, minYLabel);
                    }
                  }
              
                  this.numTicks = 12;
                }
              
                protected XPositionConverter createXPositionConverter()
                {
                  return new XPositionConverter();
                }
              
                protected YPositionConverter createYPositionConverter(boolean padPlots2) {
                  return new YPositionConverter(padPlots2, 
                    this.linePlotPreferencesHelper.getForceYAxisToStartAtZero());
                }
              
                private void updateLabelsAndAxes(OutputProperties properties, TupleData data)
                {
                  this.xAxis = data.getXAxis();
                  DataAxis yAxis = data.getYAxis();
              
                  PointConverter converter = getConverter(data);
              
                  converter.updateLabelsAndAxes(properties, data);
              
                  if ((yAxis.getAxis().getType() == 2) && (data.length() > 0)) {
                    Map formattedValues = findOrCreateFormattedValues(
                      yAxis.getAxis());
              
                    DataPoint[] dataPoints = data.getDataPoints();
                    DataPoint firstDataPoint = dataPoints[0];
                    String yUnits = this.outputProperties.getYUnits(data);
                    formattedValues.put(firstDataPoint.formatY(yUnits), firstDataPoint);
                    for (int i = 1; i < dataPoints.length; i++)
                      if (!isWideVariationInYValues(yAxis.getAxis()))
                        formattedValues.put(dataPoints[i].formatY(yUnits), 
                          dataPoints[i]);
                  }
                }
              
                public void handleEvent(Event event)
                {
	
	           
                  Display display = event.display;
                  try
                  {
                    drawPlot(event.gc, display);
                  }
                  catch (Throwable e)
                  {
                    if (TRACE.isLoggable(Level.FINE)) {
                      e.printStackTrace();
                    }
                    TRACE.log(Level.WARNING, 
                      "SWTPlotDataDisplayer handleEvent suppressing", e);
                  }
                }
              
                public void print()
                {
                  Printer printer = new Printer();
              
                  Image image = new Image(printer, this.canvas.getBounds().width, 
                    this.canvas.getBounds().height);
                  GC gc = new GC(image);
                  drawPlot(gc, printer);
                  gc.dispose();
              
                  printer.dispose();
                  image.dispose();
                }
              
                public void copyToClipboard()
                {
                  Display copyDisplay = Display.getCurrent();
                  Image image = new Image(copyDisplay, this.canvas.getBounds().width, 
                    this.canvas.getBounds().height);
                  GC gc = new GC(image);
              
                  drawPlot(gc, copyDisplay);
                  Clipboard clipboard = new Clipboard(copyDisplay);
                  ImageTransfer transfer = ImageTransfer.getInstance();
                  clipboard.setContents(new Object[] { image.getImageData() }, 
                    new Transfer[] { transfer });
                  image.dispose();
                  gc.dispose();
                }
              
                public void save(String name) {
                  TRACE.entering(this.className, "save");
              
                  if (name != null) {
                    initialisePlot(this.dataSet, this.outputProperties);
              
                    Display display = Display.getCurrent();
                    boolean canvasNeedsDisposing = false;
              
                    if ((this.canvas == null) || (this.canvas.isDisposed())) {
                      Shell shell = new Shell(display);
                      this.canvas = new Canvas(shell, 0);
                      canvasNeedsDisposing = true;
                      int canvasWidth = this.outputProperties.getSaveWidth() != null ? 
                        this.outputProperties.getSaveWidth().intValue() : 
                        700;
                      int canvasHeight = this.outputProperties.getSaveHeight() != null ? 
                        this.outputProperties.getSaveHeight().intValue() : 
                        500;
                      this.canvas.setBounds(0, 0, canvasWidth, canvasHeight);
                    }
                    Image image = new Image(display, this.canvas.getBounds().width, 
                      this.canvas.getBounds().height);
                    GC gc = new GC(image);
                    drawPlot(gc, display);
                    ImageLoader imageLoader = new ImageLoader();
                    imageLoader.data = new ImageData[] { image.getImageData() };
              
                    String saveName = name;
              
                    imageLoader.save(saveName,this.linePlotPreferencesHelper.getImageFormat()); 
                      
              
                    gc.dispose();
                    image.dispose();
              
                    if (canvasNeedsDisposing) {
                      this.canvas.dispose();
                    }
                  }
                  TRACE.exiting(this.className, "save");
                }
              
                public String[] getFileSaveExtensions() {
                  return new String[] { "*" + getDefaultFileSaveExtension() };
                }
              
                public String getDefaultFileSaveExtension() {
                  return this.linePlotPreferencesHelper.getImageFormatExtension();
                }
              
                private void drawPlot(GC gc, Device display) {
                  TRACE.entering(this.className, "drawPlot");
              
                  boolean advanced = gc.getAdvanced();
                  gc.setAdvanced(true);
              
                  clearColoursAndFonts();
              
                  Font font = gc.getFont();
                  FontData[] data = font.getFontData();
              
                  double canvasHeightScaleFactor = this.canvas.getBounds().height / 500.0D;
                    
                  int originalHeight = data[0].getHeight();
                  int smallHeight = (int)(originalHeight * 0.7D * canvasHeightScaleFactor);
                  this.alternateLabelsFont = new Font(gc.getDevice(), data[0].getName(), 
                    (int)(originalHeight * canvasHeightScaleFactor), 
                    2);
                  this.smallAlternateLabelsFont = new Font(gc.getDevice(), data[0].getName(), 
                    smallHeight, 2);
                  this.smallLabelsFont = new Font(gc.getDevice(), data[0].getName(), 
                    smallHeight, 0);
              
                  if (!this.converters.isEmpty())
                  {
	             // deleted by wenguang.huang 
                    //this.colours = new Colours(display, this.dataSet, this.outputProperties);
              
                    this.width = this.canvas.getBounds().width;
                    this.height = this.canvas.getBounds().height;
              
                    int numberLabelsHeight = 10;
                    this.leftNumberLabelsWidth = 0;
                    this.rightNumberLabelsWidth = 0;
                    int index = 0;
                    Iterator it = this.biggestYNumberLabels.values().iterator();
                    Font origFont = gc.getFont();
                    while (it.hasNext()) {
                      index++;
              
                      String string = (String)it.next();
                      int rawExtent = gc.textExtent(string).x;
              
                      if (rawExtent > 60) {
                        gc.setFont(this.smallLabelsFont);
                        rawExtent = gc.textExtent(string).x;
                      }
                      int heightExtent = gc.textExtent(string).y;
              
                      int extent = rawExtent + heightExtent + 5 + 10;
                      if (islabelOnLeft(index)) {
                        if (extent > this.leftNumberLabelsWidth)
                          this.leftNumberLabelsWidth = extent;
                      }
                      else {
                        if (extent > this.rightNumberLabelsWidth) {
                          this.rightNumberLabelsWidth = extent;
                        }
                        numberLabelsHeight = gc.stringExtent(string).y;
                      }
              
                    }
              
                    this.rightNumberLabelsWidth = Math.max(this.rightNumberLabelsWidth, 
                      gc.textExtent("somestring").y + 
                      5 + 10);
                    this.leftNumberLabelsWidth = Math.max(this.leftNumberLabelsWidth, 
                      gc.textExtent("somestring").y + 
                      5 + 10);
                    gc.setFont(origFont);
              
                    this.infoHeight = (2 * this.axisFontHeight);
              
                    int bottomOffset = this.infoHeight + 10 + numberLabelsHeight + 
                      35;
                    int topOffset = 43;
              
                    int leftOffset = this.leftNumberLabelsWidth + 35;
                    int rightOffset = 35 + this.rightNumberLabelsWidth;
              
                    this.plotLeft = leftOffset;
                    this.plotRight = (this.width - rightOffset);
                    this.plotTop = topOffset;
                    this.plotBottom = (this.height - bottomOffset);
              
                    this.plotWidth = (this.plotRight - this.plotLeft);
                    this.plotHeight = (this.plotBottom - this.plotTop);
              
                    updateConverterLimits();
                    drawBackground(gc, display);
                    drawLabelsAndAxes(gc, display);
                    drawDataPoints(gc, display);
                    drawLegend(gc, display);
                    drawCropLimits(gc, display);
              
                    this.accessibleMessage = 
                      Messages.getString("SWTPlotDataDisplayer.canvas");
                  }
                  else
                  {
                    String[] messages;
                    //String[] messages;
                    if (this.dataSet.getVariants().length == 0) {
                      String noDataParsedMessage = 
                        Messages.getString("SWTPlotDataDisplayer.no.data.parsed");
                      messages = new String[] { noDataParsedMessage };
                    }
                    else {
                      String noDataMessage = 
                        Messages.getString("SWTPlotDataDisplayer.no.data");
                      String templateMessage = 
                        Messages.getString("SWTPlotDataDisplayer.select.template");
                      String menuMessage = 
                        Messages.getString("SWTPlotDataDisplayer.select.menu");
                      messages = new String[] { noDataMessage, templateMessage, 
                        menuMessage };
                    }
              
                    Font originalFont = gc.getFont();
                    FontData messageFontData = originalFont.getFontData()[0];
                    int messageFontHeight = (int)(messageFontData.getHeight() * canvasHeightScaleFactor);
                    messageFontData.setHeight(messageFontHeight);
                    Font messageFont = new Font(gc.getDevice(), messageFontData);
                    gc.setFont(messageFont);
              
                    StringBuffer toolTip = new StringBuffer();
                    for (int i = 0; i < messages.length; i++) {
                      String message = messages[i];
                      Point extent = gc.textExtent(message);
                      int textHeight = extent.y + 2;
                      int messageWidth = extent.x;
                      int y = this.canvas.getSize().y / 2;
                      y -= textHeight * messages.length / 2;
                      y += textHeight * i;
                      gc.drawText(message, this.canvas.getSize().x / 2 - 
                        messageWidth / 2, y);
                      toolTip.append(message);
                    }
              
                    this.accessibleMessage = toolTip.toString();
                    gc.setFont(originalFont);
                    messageFont.dispose();
                  }
              
                  Iterator conv = this.converters.values().iterator();
                  while (conv.hasNext()) {
                    PointConverter converter = (PointConverter)conv.next();
                    converter.setCalculateLegendPosition(false);
                  }
              
                  gc.setAdvanced(advanced);
                  TRACE.exiting(this.className, "drawPlot");
                }
              
                private void updateConverterLimits() {
                  Iterator iter = this.converters.values().iterator();
                  while (iter.hasNext())
                    ((PointConverter)iter.next()).refreshLimits(this.plotLeft, this.plotRight, this.plotBottom, this.plotTop);
                }
              
                private void drawBackground(GC gc, Device display)
                {
	           // deleted by wenguang.huang 
//          gc.setBackground(this.colours.getBackgroundColour());
	           //added by wenguang.huang 
                 
			   //added end by wenguang.huang 


                  gc.fillRectangle(0, 0, this.width, this.height);
                }
              
                private void drawLegend(GC gc, Device display) {
                  if (this.linePlotPreferencesHelper.getDrawLegend())
                  {
                    Color startingColour = gc.getForeground();
                    int startingLineStyle = gc.getLineStyle();
                    Font startingFont = gc.getFont();
              
                    gc.setLineWidth(this.linePlotPreferencesHelper.getLineThickness());
                    gc.setFont(this.smallLabelsFont);
              
                    IDsToDisplayProperties tupleFieldsToDisplay = this.outputProperties
                      .getTupleFieldsToDisplay();
                    Iterator labels = tupleFieldsToDisplay.getAllIDsToDisplay();
              
                    int labelIndex = -1;
              
                    if (this.position == 0)
                    {
                      if (this.converters.size() > 0) {
                        PointConverter converter = getArbitraryConverter();
                        this.position = converter.calculateLegendPosition();
                      }
                    }
              
                    if (this.dataSet != null)
                    {
                      Variant[] variants = this.dataSet.getVariants();
                      int numVariants = variants.length;
              
                      int numLabels = this.numFieldsToPlot + numVariants;
              
                      if (variants.length > 1) {
                        for (int m = 0; m < variants.length; m++) {
                          labelIndex++;
              
                          Variant variant = variants[m];
                          String variantLabel = variant.getLabel();
                       // deleted by wenguang.huang 
                          //this.colours.adjustLineColourAndStyle(gc, variantLabel,null); 
                            
                            
                          drawLegendLine(gc, labelIndex, numLabels, variantLabel);
                        }
                      }
              
                      while (labels.hasNext())
                      {
                        ID id = (ID)labels.next();
              
                        AggregateData representativeData = this.dataSet
                          .getRepresentativeData();
                        if (representativeData != null)
                        {
                          if (this.linePlotPreferencesHelper.getDrawDataLegend()) {
                            TupleData twoddata = representativeData
                              .getTupleData(id);
                            if ((twoddata != null) && (!twoddata.isEmpty()) && 
                              (twoddata.length() > 0)) {
                              labelIndex++;
                              String displayName = twoddata.getDisplayName();
                           // deleted by wenguang.huang 
                              //this.colours.adjustLineColourAndStyle(gc, null,twoddata.getLabel()); 
                                
              
                              drawLegendLine(gc, labelIndex, numLabels, 
                                displayName);
                            }
                          }
                        }
                      }
                    }
              
                    gc.setForeground(startingColour);
                    gc.setLineStyle(startingLineStyle);
                    gc.setFont(startingFont);
                  }
                }
              
                private void drawLegendLine(GC gc, int labelIndex, int numLabels, String displayName)
                {
                  int minimumFontHeight = 4;
                  int maximumFontHeight = 10;
              
                  int targetFontHeight = this.height / 2 / (
                    numLabels * gc.textExtent(displayName).y);
                  int fontHeight = Math.min(maximumFontHeight, 
                    Math.max(targetFontHeight, 
                    minimumFontHeight));
                  Font font = gc.getFont();
                  FontData[] fontData = font.getFontData();
                  for (int i = 0; i < fontData.length; i++)
                  {
                    fontData[i].setHeight(fontHeight);
                  }
                  gc.setFont(font);
              
                  if (!this.converters.isEmpty()) {
                    PointConverter converter = getArbitraryConverter();
              
                    boolean isTop = converter.legendIsTop(this.position);
                    boolean isLeft = converter.legendIsLeft(this.position);
                    int yMultiplier;
                    int y1;
                    //int yMultiplier;
                    if (isTop) {
                       y1 = this.plotTop;
                      yMultiplier = 1;
                    } else {
                      y1 = this.plotBottom;
                      yMultiplier = -1;
                    }
                    int xMultiplier;
                    int x1;
                    //int xMultiplier;
                    if (isLeft) {
                       x1 = this.plotLeft;
                      xMultiplier = 1;
                    } else {
                      x1 = this.plotRight;
                      xMultiplier = -1;
                    }
              
                    int ySpacing = (int)(1.3D * gc.textExtent(displayName).y);
              
                    x1 += xMultiplier * 20;
                    y1 += yMultiplier * (20 + labelIndex * ySpacing);
              
                    int lineY = y1 + (int)(0.5D * gc.textExtent(displayName).y);
                    gc
                      .drawLine(x1, lineY, x1 + xMultiplier * 20, 
                      lineY);
                    int textOffset = 0;
                    if (!isLeft) {
                      textOffset = gc.textExtent(displayName).x;
                    }
                    gc.drawText(displayName, x1 + xMultiplier * (
                      20 + textOffset), y1);
                  }
                }
              
                private PointConverter getArbitraryConverter() {
                  return (PointConverter)this.converters.values().iterator().next();
                }
              
                private void drawCropLimits(GC gc, Device device) {
                  String baseUnits = this.xAxis.getAxis().getBaseUnitName();
                  if ((this.outputProperties.getMinimumX(baseUnits) == null) && 
                    (this.outputProperties.getMaximumX(baseUnits) == null)) {
                    return;
                  }
                  Pattern pattern = new Pattern(device, 0.0F, 0.0F, 1.0F, 1.0F, 
                    gc.getBackground(), 0, gc.getForeground(), 96);
                  if (this.outputProperties.getMinimumX(baseUnits) != null) {
                    Double minX = this.outputProperties.getMinimumX(baseUnits);
                    int minXPosition = this.xConverter.convertToPosition(minX.doubleValue());
                    drawCropBar(gc, pattern, minXPosition, true);
                  }
                  if (this.outputProperties.getMaximumX(baseUnits) != null) {
                    Double maxX = this.outputProperties.getMaximumX(baseUnits);
                    int maxXPosition = this.xConverter.convertToPosition(maxX.doubleValue());
                    drawCropBar(gc, pattern, maxXPosition, false);
                  }
                  pattern.dispose();
                }
              
                private void drawCropBar(GC gc, Pattern pattern, int xPosition, boolean leftHandSide)
                {
                  int yTop = this.plotTop;
                  int yBottom = this.plotBottom;
                  if ((xPosition > this.plotLeft) && (xPosition < this.plotRight)) {
                    gc.drawLine(xPosition, yTop, xPosition, yBottom);
                    int[] topTriangle = { xPosition - 5, yTop - 5, xPosition + 5, 
                      yTop - 5, xPosition, yTop };
                    int[] bottomTriangle = { xPosition - 5, yBottom + 5, xPosition + 5, 
                      yBottom + 5, xPosition, yBottom };
                    gc.drawPolygon(topTriangle);
              
                    if (gc.getAdvanced()) {
                      gc.drawPolygon(bottomTriangle);
                      gc.setBackgroundPattern(pattern);
                      if (leftHandSide)
                        gc.fillRectangle(this.plotLeft, yTop, xPosition - this.plotLeft, 
                          yBottom - yTop);
                      else {
                        gc.fillRectangle(xPosition, yTop, this.plotRight - xPosition, 
                          yBottom - yTop);
                      }
                      gc.setBackgroundPattern(null);
                    }
                  }
                }
              
                private boolean islabelOnLeft(int number) {
                  return number % 2 != 0;
                }
              
                private final boolean isWideVariationInYValues(Axis axis) {
                  Map formattedValues = (Map)this.pointRecord.get(axis);
                  if (formattedValues != null) {
                    return formattedValues.size() > this.numTicks;
                  }
                  return false;
                }
              
                private PointConverter getConverter(TupleData tupleData)
                {
                  PointConverter converter = (PointConverter)this.converters.get(tupleData.getYAxis());
                  if (converter == null)
                  {
                    YPositionConverter yConverter = createYPositionConverter(this.padPlots);
                    converter = new PointConverter(this.xConverter, yConverter);
              
                    this.converters.put(tupleData.getYAxis(), converter);
                  }
                  return converter;
                }
              
                private Map<String, DataPoint> findOrCreateFormattedValues(Axis axis)
                {
                  Map formattedValues = (Map)this.pointRecord.get(axis);
                  if (formattedValues == null) {
                    formattedValues = new TreeMap();
                    this.pointRecord.put(axis, formattedValues);
                  }
                  return formattedValues;
                }
              
                private void drawDataPoints(GC gc, Device display)
                {
                  Color startingColour = gc.getForeground();
                  int startingLineStyle = gc.getLineStyle();
                  gc.setClipping(this.plotLeft, this.plotTop, this.plotWidth, this.plotHeight);
//           deleted by wenguang.huang 
               //gc.setLineWidth(this.linePlotPreferencesHelper.getLineThickness());
//          added by wenguang.huang 
               gc.setLineWidth(2);
               //added end by wenguang.huang 
             

                  Iterator labels = this.outputProperties.getTupleFieldsToDisplay()
                    .getAllIDsToDisplay();
              
                  int labelIndex = -1;
              
                  while (labels.hasNext()) {
                    labelIndex++;
              
                    ID id = (ID)labels.next();
              
                    if (this.dataSet != null)
                    {
                      Variant[] variants = this.dataSet.getVariants();
              
                      for (int m = 0; m < variants.length; m++) {
                        TupleData twoddata = variants[m].getTupleData(id);
                        if ((twoddata != null) && (!twoddata.isEmpty()))
                        {
                          int type = twoddata.getYAxis().getAxis()
                            .getType();
                          String label = twoddata.getLabel();
                       // deleted by wenguang.huang 
                          //this.colours.adjustLineColourAndStyle(gc,variants[m].getLabel(), label); 
                            
              
                          if (type == 0)
                            drawDataPointsForTimeSeriesRun(gc, label, 
                              labelIndex, twoddata);
                          else if (type == 2)
                            drawDataPointsForDiscreteRun(gc, label, labelIndex, 
                              twoddata);
                          else
                            drawDataPointsForBinaryRun(gc, label, labelIndex, 
                              twoddata);
                        }
                      }
                    }
                    else {
                      TRACE.fine("The data set to draw is null.");
                    }
              
                  }
              
                  gc.setForeground(startingColour);
                  gc.setLineStyle(startingLineStyle);
              
               // deleted by wenguang.huang 
                 // gc.setClipping(null);
                }
              
                private void drawDataPointsForDiscreteRun(GC gc, String label, int labelIndex, TupleData twoddata)
                {
                  PointConverter converter = getConverter(twoddata);
              
                  DataPoint[] dataPoints = twoddata.getDataPoints();
                  int numPoints = dataPoints.length;
                  if (numPoints > 0)
                  {
                    DataPoint firstDataPoint = dataPoints[0];
                    Point firstPoint = converter.convertToPoint(firstDataPoint);
                    int radius = 2;
                    int x2 = firstPoint.x - radius;
                    int y2 = firstPoint.y - radius;
                    gc.drawOval(x2, y2, 3, 3);
              
                    if (numPoints > 1)
                    {
                      for (int j = 1; j < numPoints; j++)
                      {
                        int x1 = x2;
                        int y1 = y2;
              
                        DataPoint dataPoint = dataPoints[j];
                        Point point = converter.convertToPoint(dataPoint);
                        x2 = point.x - radius;
                        y2 = point.y - radius;
              
                        if ((x2 != x1) || (y2 != y1))
                        {
                          gc.drawOval(x2, y2, 3, 3);
                        }
                      }
                    }
                  }
                }
              
                private void drawDataPointsForBinaryRun(GC gc, String label, int labelIndex, TupleData twoddata)
                {
                  PointConverter converter = getConverter(twoddata);
              
                  DataPoint[] dataPoints = twoddata.getDataPoints();
                  int numPoints = dataPoints.length;
                  if (numPoints > 0)
                  {
                    DataPoint firstDataPoint = dataPoints[0];
                    Point firstPoint = converter.convertToPoint(firstDataPoint);
                    int x2 = firstPoint.x;
                    int y2 = firstPoint.y;
              
                    gc.drawLine(x2, this.plotTop, x2, this.plotBottom);
              
                    if (numPoints > 1)
                    {
                      for (int j = 1; j < numPoints; j++)
                      {
                        int x1 = x2;
                        int y1 = y2;
              
                        DataPoint dataPoint = dataPoints[j];
                        Point point = converter.convertToPoint(dataPoint);
                        x2 = point.x;
                        y2 = point.y;
              
                        if ((x2 != x1) || (y2 != y1))
                        {
                          gc.drawLine(x2, this.plotTop, x2, this.plotBottom);
                        }
                      }
                    }
                  }
                }
              
                private void drawDataPointsForTimeSeriesRun(GC gc, String label, int labelIndex, TupleData twoddata)
                {
                  PointConverter converter = getConverter(twoddata);
                  Axis axis = twoddata.getYAxis().getAxis();
                  PriorityQueue dataPoints = twoddata.getSortedDataPoints();
                  int numPoints = dataPoints.size();
                  if (numPoints > 0)
                  {
                    if (numPoints > 1) {
                      int[] points = preparePointArray(dataPoints, converter, axis);
              
                      int antialias = gc.getAntialias();
                      if (gc.getAdvanced()) {
                        gc.setAntialias(1);
                      }
                      gc.drawPolyline(points);
                      if (gc.getAdvanced())
                        gc.setAntialias(antialias);
                    }
                  }
                }
              
                private void drawLabelsAndAxes(GC gc, Device display)
                {
                  double minXValue = this.xConverter.convertToValue(this.plotLeft);
                  double maxXValue = this.xConverter.convertToValue(this.plotRight);
                  double xValueRange = maxXValue - minXValue;
              
                  String xUnits = this.outputProperties.getUnits(this.xAxis.getAxis());
                  double xTickRange;
/*      *///          double xTickRange;
                  if ((VGCAxes.DATE.equals(xUnits)) || (VGCAxes.DAYS.equals(xUnits)))
                    xTickRange = calculateTickWidthValueForDaysAndDate(xValueRange);
                  else {
                    xTickRange = calculateTickWidthValue(xValueRange);
                  }
                  drawXTicks(gc, minXValue, maxXValue, xTickRange);
              
                  int yAxisCount = 0;
                  List leftLabels = new LinkedList();
                  List rightLabels = new LinkedList();
                  this.axes = new DataAxis[4];
              
                  this.usedYTicksLeft = new TreeSet();
                  this.usedYTicksRight = new TreeSet();
              
                  for (DataAxis yAxis : this.converters.keySet())
                  {
                    if (yAxis.getAxis().getType() != 1)
                    {
                      String units = this.outputProperties.getUnits(yAxis.getAxis());
                      String yUnitLabel = MessageFormat.format("{0} ({1})", new Object[] { 
                        yAxis.getLabel(), units });
              
                      if (yAxisCount < 4) {
                        this.axes[yAxisCount] = yAxis;
                      }
                      boolean onLeft = yAxisCount % 2 == 0;
                      boolean primary = yAxisCount < 2;
                      if (onLeft)
                        leftLabels.add(yUnitLabel);
                      else {
                        rightLabels.add(yUnitLabel);
                      }
                      if (yAxis.getAxis().getType() == 2)
                      {
                        drawYDiscreteTicks(gc, yAxis, onLeft, primary);
                        yAxisCount++;
                      }
                      if (yAxis.getAxis().getType() == 0)
                      {
                        YPositionConverter yConverter = ((PointConverter)this.converters.get(yAxis))
                          .getYConverter();
                        double minYValue = yConverter.convertToValue(this.plotBottom);
                        double maxYValue = yConverter.convertToValue(this.plotTop);
                        double yValueRange = maxYValue - minYValue;
                        double yTickRange = calculateTickWidthValue(yValueRange);
              
                        drawYTimeSeriesTicks(gc, yConverter, yAxis, yTickRange, onLeft, 
                          primary);
                        yAxisCount++;
                      }
                    }
                  }
              
                  this.usedYTicksLeft = null;
                  this.usedYTicksRight = null;
                  drawYUnitLabels(gc, leftLabels, true);
                  drawYUnitLabels(gc, rightLabels, false);
                  
               // deleted by wenguang.huang 
//          gc.setForeground(this.colours.getAxisColour());
                  gc.drawRectangle(this.plotLeft, this.plotTop, this.plotWidth, this.plotHeight);
                }
              
                private static double calculateTickWidthValue(double valueRange)
                {
                  double unit = 1.0D;
                  if (valueRange > 10.0D) {
                    while (unit / valueRange < 0.1D) {
                      unit *= 10.0D;
                    }
                    if (2.0D * unit > valueRange) {
                      unit /= 10.0D;
                    }
                  }
                  else if (valueRange > 0.0D) {
                    while (unit / valueRange > 0.1D) {
                      unit /= 10.0D;
                    }
                    if (2.0D * unit > valueRange) {
                      unit *= 10.0D;
                    }
                  }
              
                  double tickRange = unit;
                  if (valueRange / tickRange < 5.0D) {
                    tickRange = unit / 2.0D;
                    if (valueRange / tickRange < 5.0D)
                      tickRange = unit / 5.0D;
                  }
                  else if (valueRange / tickRange > 12.0D) {
                    tickRange = unit * 2.0D;
                    if (valueRange / tickRange > 12.0D) {
                      tickRange = unit * 5.0D;
                    }
                  }
                  return tickRange;
                }
              
                private static double calculateTickWidthValueForDaysAndDate(double valueRange)
                {
                  if (valueRange < 900000.0D)
                  {
                    return 60000.0D;
                  }if (valueRange < 1800000.0D)
                  {
                    return 120000.0D;
                  }if (valueRange < 3600000.0D)
                  {
                    return 300000.0D;
                  }if (valueRange < 7200000.0D)
                  {
                    return 600000.0D;
                  }if (valueRange < 14400000.0D)
                  {
                    return 1200000.0D;
                  }if (valueRange < 21600000.0D)
                  {
                    return 1800000.0D;
                  }if (valueRange < 43200000.0D)
                  {
                    return 3600000.0D;
                  }if (valueRange < 86400000.0D)
                  {
                    return 7200000.0D;
                  }if (valueRange < 172800000.0D)
                  {
                    return 14400000.0D;
                  }if (valueRange < 345600000.0D)
                  {
                    return 28800000.0D;
                  }if (valueRange < 691200000.0D)
                  {
                    return 57600000.0D;
                  }if (valueRange < 1382400000.0D)
                  {
                    return 86400000.0D;
                  }
              
                  double rangeInDays = Math.rint(valueRange / 86400000.0D);
                  return 86400000.0D * Math.rint(rangeInDays / 10.0D);
                }
              
                private void drawXTicks(GC gc, double minValue, double maxValue, double tickRange)
                {
                  double firstTickValue = Math.ceil(minValue / tickRange) * tickRange;
                  double currentTickValue = firstTickValue;
                  if (currentTickValue == -0.0D) {
                    currentTickValue = 0.0D;
                  }
                  int lastLabelEndX = -2147483648;
                  boolean twoLinesOfLabels = false;
              
                  double tickPrecision = getFractionDigits(tickRange);
                  int fractionDigits = (int)Math.round(tickPrecision);
                  double tickCount = 0.0D;
                  do
                  {
                    int currentTickPosition = this.xConverter
                      .convertToPosition(currentTickValue);
              
                    String currentTickLabel = this.xAxis.formatUnconverted(currentTickValue, 
                      fractionDigits, this.outputProperties.getUnits(this.xAxis.getAxis()));
                    // deleted by wenguang.huang 
                    //gc.setForeground(this.colours.getTicksColour());
                    drawVerticalBackGroundLine(gc, currentTickPosition, this.plotTop, 
                      this.plotBottom + 10);
                    Point labelDimensions = gc.textExtent(currentTickLabel);
                    int labelXPosition = currentTickPosition - labelDimensions.x / 2;
                    int labelYPosition = this.plotBottom + 10 + 
                      labelDimensions.y / 2;
              
                    if (labelXPosition > lastLabelEndX) {
                      lastLabelEndX = currentTickPosition + labelDimensions.x / 2;
                    } else {
                      lastLabelEndX = -2147483648;
                      labelYPosition += labelDimensions.y;
                      twoLinesOfLabels = true;
                    }
                 // deleted by wenguang.huang 
                    //gc.setForeground(this.colours.getAxisColour());
                    gc.drawText(currentTickLabel, labelXPosition, labelYPosition);
              
                    tickCount += 1.0D;
                    currentTickValue = firstTickValue + tickRange * tickCount;
                  }
                  while (currentTickValue < maxValue);
              
                  drawXUnitLabel(gc, twoLinesOfLabels);
                }
              
                private void drawXUnitLabel(GC gc, boolean twoLinesOfLabels)
                {
                  String units = this.outputProperties.getUnits(this.xAxis.getAxis());
                  String xUnitLabel = MessageFormat.format("{0} ({1})", new Object[] { 
                    this.xAxis.getConverterDefinition(units).getLabel(), units });
                  Point textSize = gc.textExtent(xUnitLabel);
                  int unitLabelXPosition = this.plotLeft + this.plotWidth / 2 - textSize.x / 2;
              
                  int unitLabelYPosition = this.plotBottom + 10 + textSize.y + 
                    textSize.y / 2;
                  if (twoLinesOfLabels) {
                    unitLabelYPosition += textSize.y;
                  }
                  gc.drawText(xUnitLabel, unitLabelXPosition, unitLabelYPosition);
                }
              
                private void drawYTimeSeriesTicks(GC gc, YPositionConverter yConverter, DataAxis yAxis, double tickRange, boolean onLeft, boolean primary)
                {
                  double minYValue = yConverter.convertToValue(this.plotBottom);
                  double maxYValue = yConverter.convertToValue(this.plotTop);
                  double firstTickValue = Math.ceil(minYValue / tickRange) * tickRange;
                  double currentTickValue = firstTickValue;
                  if (currentTickValue == -0.0D) {
                    currentTickValue = 0.0D;
                  }
                  double tickCount = 0.0D;
              
                  double tickPrecision = getFractionDigits(tickRange);
                  int fractionDigits = (int)Math.round(tickPrecision);
                  do
                  {
                    int currentTickPosition = yConverter
                      .convertToPosition(currentTickValue);
                    String currentTickLabel = yAxis.formatUnconverted(currentTickValue, 
                      fractionDigits, this.outputProperties.getUnits(yAxis.getAxis()));
                    drawYTick(gc, currentTickPosition, currentTickLabel, onLeft, 
                      primary);
              
                    tickCount += 1.0D;
                    currentTickValue = firstTickValue + tickRange * tickCount;
                  }
                  while (currentTickValue < maxYValue);
                }
              
                private double getFractionDigits(double tickRange) {
                  double tickPrecision = 0.0D;
                  if (tickRange > 10.0D) {
                    tickPrecision = 0.0D;
                  } else if (tickRange > 1.0D) {
                    tickPrecision = 1.0D;
                  } else {
                    tickPrecision = Math.abs(Math.log10(tickRange));
                    tickPrecision += 1.0D;
                  }
                  return tickPrecision;
                }
              
                private void drawYDiscreteTicks(GC gc, DataAxis yAxis, boolean onLeft, boolean primary)
                {
                  Map formattedValues = findOrCreateFormattedValues(
                    yAxis.getAxis());
                  for (Object entry : formattedValues.entrySet()) {
                    String label = (String)((Map.Entry)entry).getKey();
                    DataPoint point = (DataPoint)((Map.Entry)entry).getValue();
                    YPositionConverter yConverter = ((PointConverter)this.converters.get(yAxis))
                      .getYConverter();
                    int tickYPosition = yConverter.convertToPosition(
                      point.getY(this.outputProperties.getUnits(yAxis.getAxis())));
                    drawYTick(gc, tickYPosition, label, onLeft, primary);
                  }
                }
              
                private boolean aquireYTickPosition(GC gc, int yPosition, String currentTickLabel, boolean onLeft)
                {
                  int yBottom = yPosition + gc.textExtent(currentTickLabel).y;
                  TreeSet usedYTicks = onLeft ? this.usedYTicksLeft : 
                    this.usedYTicksRight;
              
                  for (int y = yPosition; y < yBottom + 1; y++) {
                    if (usedYTicks.contains(Integer.valueOf(y))) {
                      return false;
                    }
                  }
              
                  for (int y = yPosition; y < yBottom; y++) {
                    usedYTicks.add(Integer.valueOf(y));
                  }
                  return true;
                }
              
                private void drawYTick(GC gc, int currentTickYPosition, String currentTickLabel, boolean onLeft, boolean primary)
                {
                  if (!aquireYTickPosition(gc, currentTickYPosition, currentTickLabel, 
                    onLeft)) {
                    return;
                  }
              
                  int lineStart = 0;
                  int lineEnd = 0;
                  int labelXPosition = 0;
                  Point labelDimensions = gc.textExtent(currentTickLabel);
                  if (onLeft) {
                    lineStart = this.plotLeft - 10;
                    if (primary)
                      lineEnd = this.plotRight;
                    else {
                      lineEnd = this.plotLeft + 10;
                    }
                    labelXPosition = this.plotLeft - (labelDimensions.x + 10);
              
                    labelXPosition = Math.max(labelXPosition, 0);
                  } else {
                    lineStart = this.plotRight - 10;
                    lineEnd = this.plotRight + 10;
                    labelXPosition = this.plotRight + 10;
              
                    labelXPosition = Math.min(labelXPosition, this.canvas.getSize().x - 
                      labelDimensions.x);
                  }
                  int labelYPosition = currentTickYPosition - labelDimensions.y / 2;
              
               // deleted by wenguang.huang 
//          if ((primary) && (onLeft))
                    //gc.setForeground(this.colours.getTicksColour());
                 // else {
//            gc.setForeground(this.colours.getAxisColour());
                 // }
              
                  drawHorizontalBackGroundLine(gc, currentTickYPosition, lineStart, 
                    lineEnd);
               // deleted by wenguang.huang 
//          gc.setForeground(this.colours.getAxisColour());
                  gc.drawText(currentTickLabel, labelXPosition, labelYPosition);
                }
              
                private void drawHorizontalBackGroundLine(GC gc, int currentTickYPosition, int lineStart, int lineEnd)
                {
                  if (lineStart == lineEnd)
                  {
                    return;
                  }
                  gc.drawLine(lineStart, currentTickYPosition, lineEnd, 
                    currentTickYPosition);
                }
              
                private void drawVerticalBackGroundLine(GC gc, int currentTickXPosition, int lineStart, int lineEnd)
                {
                  if (lineStart == lineEnd)
                  {
                    return;
                  }
                  gc.drawLine(currentTickXPosition, lineStart, currentTickXPosition, 
                    lineEnd);
                }
              
                private void drawYUnitLabels(GC gc, List<String> labels, boolean onLeft)
                {
                  if (gc.getAdvanced())
                  {
                    int unitLabelXPosition = 0;
                    if (onLeft) {
                      unitLabelXPosition = 35;
                    }
                    else {
                      unitLabelXPosition = this.canvas.getSize().x - 35;
                    }
                    float rotation = onLeft ? -90.0F : 90.0F;
                    Transform transform = new Transform(gc.getDevice());
                    transform.rotate(rotation);
                    gc.setTransform(transform);
                    for (int i = 0; i < labels.size(); i++) {
                      String label = (String)labels.get(i);
                      Point textSize = gc.textExtent(label);
                      int unitLabelYOffset = this.plotHeight / (labels.size() + 1) * (i + 1);
                      unitLabelYOffset -= textSize.y / 2;
                      int unitLabelYPosition = this.plotTop + unitLabelYOffset;
              
                      if (onLeft)
                        gc.drawText(label, -unitLabelYPosition, 
                          unitLabelXPosition);
                      else {
                        gc.drawText(label, unitLabelYPosition, 
                          -unitLabelXPosition);
                      }
                    }
                    transform.rotate(rotation * -1.0F);
                    gc.setTransform(null);
                  }
                  else {
                    int unitLabelXPosition = 0;
                    if (onLeft) {
                      unitLabelXPosition = 35;
                    }
                    else {
                      unitLabelXPosition = this.canvas.getSize().x - 35;
                    }
                    for (int i = 0; i < labels.size(); i++) {
                      String label = (String)labels.get(i);
                      Point textSize = gc.textExtent(label);
                      int unitLabelYOffset = this.plotHeight / (labels.size() + 1) * (i + 1);
                      unitLabelYOffset -= textSize.y / 2;
                      int unitLabelYPosition = this.plotTop + unitLabelYOffset;
                      int textLength = textSize.x;
              
                      if (onLeft)
                        gc.drawText(label, 
                          Math.max(unitLabelXPosition - 
                          textLength / 2, 0), unitLabelYPosition);
                      else
                        gc.drawText(label, 
                          Math.min(unitLabelXPosition - 
                          textLength / 2, this.canvas.getSize().x - 
                          textLength / 2), unitLabelYPosition);
                    }
                  }
                }
              
                private int[] preparePointArray(PriorityQueue<DataPoint> dataPoints, PointConverter converter, Axis axis)
                {
                  int numPoints = dataPoints.size();
              
                  Point point0 = converter.convertToPoint((DataPoint)dataPoints.poll());
                  int x2 = point0.x;
                  int y2 = point0.y;
              
                  int lowY = 2147483647; int highY = -2147483648;
              
                  int lastY = y2;
                  boolean inSequence = false;
              
                  int[] points = new int[(numPoints + 3) * 2];
                  int index = 0;
                  index = addPoint(x2, y2, points, index);
              
                  Iterator it = dataPoints.iterator();
                  it.next();
              
                  DataPoint dataPoint = (DataPoint)dataPoints.poll();
                  while (dataPoint != null)
                  {
                    int y1 = y2;
                    int x1 = x2;
              
                    Point point = converter.convertToPoint(dataPoint);
                    x2 = point.x;
                    y2 = point.y;
              
                    if (x1 == x2)
                    {
                      inSequence = true;
                      lowY = Math.min(lowY, y2);
                      highY = Math.max(highY, y2);
                    }
                    else {
                      if (inSequence)
                      {
                        if (lowY != highY) {
                          if ((lowY != y1) && (lowY != lastY)) {
                            index = addPoint(x1, lowY, points, index);
                          }
                          if ((highY != y1) && (highY != lastY)) {
                            index = addPoint(x1, highY, points, index);
                          }
              
                          index = addPoint(x1, y1, points, index);
                        }
              
                        inSequence = false;
                      }
              
                      index = addPoint(x2, y2, points, index);
              
                      lowY = y2;
                      highY = y2;
                      lastY = y2;
                    }
                    dataPoint = (DataPoint)dataPoints.poll();
                  }
              
                  index = addPoint(x2, lowY, points, index);
                  index = addPoint(x2, highY, points, index);
                  index = addPoint(x2, y2, points, index);
                  int[] shortenedPoints;
                  if (index < points.length) {
                    shortenedPoints = new int[index];
                    for (int i = 0; i < index; i++)
                      shortenedPoints[i] = points[i];
                  }
                  else {
                    shortenedPoints = points;
                  }
                  return shortenedPoints;
                }
              
                private final int addPoint(int x2, int y2, int[] points, int index) {
                  if (index < points.length - 1) {
                    points[index] = x2;
                    index++;
                    points[index] = y2;
                    index++;
                  }
                  return index;
                }
              
                public void dispose() {
                  clearColoursAndFonts();
                }
              
                private void clearColoursAndFonts()
                {
                  if (this.colours != null) {
                    this.colours.dispose();
                    this.colours = null;
                  }
                  if (this.alternateLabelsFont != null) {
                    this.alternateLabelsFont.dispose();
                    this.alternateLabelsFont = null;
                  }
                  if (this.smallAlternateLabelsFont != null) {
                    this.smallAlternateLabelsFont.dispose();
                    this.smallAlternateLabelsFont = null;
                  }
                  if (this.smallLabelsFont != null) {
                    this.smallLabelsFont.dispose();
                    this.smallLabelsFont = null;
                  }
                }
              
                public void mouseMove(MouseEvent e)
                {
                  ISelection selection = StructuredSelection.EMPTY;
              
                  if ((e.x > this.plotLeft) && (e.x < this.plotRight) && (e.y > this.plotTop) && 
                    (e.y < this.plotBottom)) {
                    DataPoint point = getDataPoint(new Point(e.x, e.y));
                    if (point != null)
                      selection = new DataPointSelection(point);
                  }
                  else
                  {
                    DataAxis axis = getAxis(new Point(e.x, e.y));
              
                    if (axis != null) {
                      selection = new AxisSelection(axis);
                    }
                  }
                  getSelectionProvider().setSelection(selection);
                }
              
                private DataAxis getAxis(Point point) {
                  DataAxis axis = null;
                  if (point.y > this.plotBottom) {
                    if (this.xAxis != null)
                      axis = this.xAxis;
                  }
                  else if (point.x < this.plotLeft)
                  {
                    if (this.axes[2] == null) {
                      axis = this.axes[0];
                    }
                    else if (point.y < this.height / 2)
                      axis = this.axes[0];
                    else {
                      axis = this.axes[2];
                    }
                  }
                  else if (point.x > this.plotRight) {
                    if (this.axes[3] == null) {
                      axis = this.axes[1];
                    }
                    else if (point.y < this.height / 2)
                      axis = this.axes[1];
                    else {
                      axis = this.axes[3];
                    }
                  }
              
                  return axis;
                }
              
                public String getDescription(Point point)
                {
                  DataPoint dataPoint = null;
                  YDataAxis yAxis = null;
                  for (Map.Entry entry : this.converters.entrySet()) {
                    PointConverter converter = (PointConverter)entry.getValue();
                    dataPoint = converter.findDataPoint(point);
                    if (dataPoint != null)
                    {
                      yAxis = (YDataAxis)entry.getKey();
                      break;
                    }
                  }
                  if ((dataPoint != null) && (yAxis != null)) {
                    String xUnits = this.outputProperties.getUnits(this.xAxis.getAxis());
                    String yUnits = this.outputProperties.getUnits(yAxis.getAxis());
                    String xString = dataPoint.formatXWithUnits(xUnits);
                    String yString = dataPoint.formatYWithUnits(yUnits);
                    String comment = dataPoint.getComment();
                    String description = MessageFormat.format(POINT_HOVERTEXT_FORMAT, 
                      new Object[] { xString, yString, comment });
                    return description;
                  }
              
                  DataAxis axis = getAxis(point);
                  if (axis != null) {
                    String units = this.outputProperties.getUnits(axis.getAxis());
                    String axisLabel;
                    //String axisLabel;
                    if ((axis instanceof YDataAxis))
                      axisLabel = MessageFormat.format("{0} ({1})", new Object[] { 
                        axis.getLabel(), units });
                    else {
                      axisLabel = MessageFormat.format("{0} ({1})", new Object[] { 
                        axis.getConverterDefinition(units).getLabel(), units });
                    }
                    return axisLabel;
                  }
              
                  return null;
                }
              
                public ISelectionProvider getSelectionProvider() {
                  return this.selectionProvider;
                }
              }

